package com.ckzp.jfinal.interceptor;

import com.alibaba.fastjson.JSON;
import com.ckzp.core.ConfigUtil;
import com.ckzp.core.Results;
import com.ckzp.core.id.UUIDHex;
import com.ckzp.core.json.Jmode;
import com.ckzp.core.json.JsonResult;
import com.ckzp.core.json.JsonUtil;
import com.ckzp.core.model.Datas;
import com.ckzp.core.util.ClientUtil;
import com.ckzp.core.util.JwtUtil;
import com.ckzp.core.util.StringUtil;
import com.ckzp.jfinal.system.WebSite;
import com.ckzp.jfinal.system.cache.SysActivityCache;
import com.ckzp.jfinal.system.cache.SysConfigCache;
import com.ckzp.jfinal.system.tools.ValidateRole;
import com.ckzp.jfinal.system.util.SysOnlineUtil;
import com.ckzp.jfinal.system.util.SysWorkLogUtil;
import com.ckzp.jfinal.system.util.LoginUtil;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * Created by 51594 on 2022/7/27.
 */
public class AuthInterceptor implements Interceptor {

    /**
     * DEBUG
     * 在web.properties中定义
     */
    public static boolean DEBUG = ConfigUtil.DEBUG();

    /**
     * 系统版本号
     * 在系统管理中定义
     */
    public static String VERSION = null;

    /**
     * @param inv
     */
    public void intercept(Invocation inv) {

        if (VERSION == null) VERSION = SysConfigCache.getConfigValue("version");

        Results results = new Results();
        //
        boolean HasRole = false, IsApi = false;//不需鉴权,
        //管理
        boolean HasAdmin = false;
        String name = "菜单名称", pass_roles = "|administrator|", user_roles = "";

        Method menthod = inv.getMethod();
        String menthod_name = inv.getMethodName();
        //////如果是Api结束，判断为api,api默认renderJson
        if (menthod_name.endsWith("Api")) {
            IsApi = true;
        }
        //系统方法中写的权限,读取出来
        String act_path = inv.getControllerKey() + "/" + inv.getMethodName();
        //系统方法中写的权限,读取出来
        Roles roles = menthod.getDeclaredAnnotation(Roles.class);
        Admins as = menthod.getDeclaredAnnotation(Admins.class);
        String def_role = "";
        if (roles != null) {
            if (roles.roles() != null && roles.roles().length() > 0) {
                HasRole = false;//need鉴权
                def_role += roles.roles() + "|";
            }
        }
        ////////////////////////////////////////////////////////////
        if (as != null) {
            if (as.roles() != null && as.roles().length() > 0) {
                HasRole = false;//need鉴权
                def_role += as.roles() + "|";
            }
            if (as.name() != null && as.name().length() > 0) {
                name = as.name();
            }
            //需要记录日志
        }
        ///////////////////////////////////////////////////////////////
        //从系统 菜单表中取权限，如果没有，创建菜单
        AuthActivity act = AuthActivity.n().setAct_name(name).setAct_role(def_role).setAct_path(act_path);
        act = SysActivityCache.getActivityRole(act);//从系统中取值
        String act_ids = "act_" + act.getAct_id();
        name = act.getAct_name();
        String menu_role = "|" + act.getAct_role() + "|";
        if (act.isIs_log()) {
            //////////////传入的参数//////////////////////////////////////
            String para = JSON.toJSONString(inv.getController().getParaMap());
            int emp_id = getEmpID(inv.getController().getRequest());
            SysWorkLogUtil.n().saveLog(String.valueOf(emp_id), act_ids, act_path,
                    act.getAct_name(), para, ClientUtil.getIp(inv.getController().getRequest()));
            ////////////////////////////////////////////////////g
        }
        //需要验证的权限
        pass_roles = pass_roles + menu_role;
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        if (!HasRole) {
            String jwt = WebSite.getJwt(inv.getController().getRequest());
            results = JwtUtil.validateJWT(jwt);
            if (results.getCode() == 0) {
                JwtUtil.JwtSubject js = results.getObject(JwtUtil.JwtSubject.class);
                inv.getController().setAttr("emp_id", js.getUserid());
                inv.getController().setAttr("user_name", js.getUsername());
                inv.getController().setAttr("user_role", js.getRoles());
                //如果超过1小时没刷新，刷新jwt
                if (System.currentTimeMillis() - js.getLastlogin() > (60 * 60 * 1000)) {
                    JwtUtil.JwtSubject js1 = new JwtUtil.JwtSubject(js.getUserid(), js.getDeptid(), js.getUsername(), js.getRoles(), System.currentTimeMillis()).setId(UUIDHex.getUUIDHex());
                    jwt = JwtUtil.createJWT(js1.getId(), js1, LoginUtil.EXPRESS_LOGIN_TIME);
                    WebSite.setJwt(inv.getController().getResponse(), jwt);
                    inv.getController().setAttr("jwt", jwt);
                }
                user_roles = js.getRoles() + "|login|";
                if (user_roles != null) {
                    String[] user_roless = StringUtil.split(user_roles, "|");
                    for (int k = 0; k < user_roless.length; k++) {
                        String role = user_roless[k];
                        if (role != null && role.length() > 0 && pass_roles.indexOf("|" + role + "|") > -1) {
                            HasRole = true;
                            break;
                        }
                    }
                }
            } else {
                HasRole = false;
            }
        }
        //////////////////////////////////////////////////////////////////////////////////////////////////////////
        if (DEBUG) {
            System.out.println("-----------------------auth---------------------------------------------");
            System.out.println("act_id             :" + act_ids);
            System.out.println("act_path           :" + act_path);
            System.out.println("act_name           :" + name);
            System.out.println("act log            :" + act.isIs_log());
            System.out.println("viewpath           :" + inv.getViewPath());
            System.out.println("Method             :" + inv.getMethodName());
            System.out.println("sess id            :" + getSessId(inv.getController().getRequest()));
            System.out.println("need roles         :" + pass_roles);
            System.out.println("user roles         :" + user_roles);
            System.out.println("result roles       :" + HasRole);
            System.out.println("result admin       :" + HasAdmin);
            System.out.println("result msg         :" + results.getMessage());
            //  System.out.println("request            :" + getRequestJson(inv.getController()));
            System.out.println("-----------------------auth end ---------------------------------------------");
        }
        ////////////////////////////////付值/////////////////////////////////////////////////////////////////////////////
        if (HasRole) {
            ////////////////////////配置通用变量//////////////////////////////
            String sessid = getSessId(inv.getController().getRequest());
            SysOnlineUtil.n().saveActive(sessid);
            ///////////////////////////////////////////////////////
            inv.getController().setAttr("admin", HasAdmin);
            inv.getController().setAttr("version", VERSION);
            inv.getController().setAttr("debug", DEBUG);
            inv.getController().setAttr("time", System.currentTimeMillis());
            inv.getController().setAttr("R", ValidateRole.n(WebSite.getJwt(inv.getController().getRequest())));
            inv.invoke();
        } else {
            inv.getController().setAttr("path", ConfigUtil.getWebPath());
            inv.getController().setAttr("adminpath", ConfigUtil.getWebPath() + ConfigUtil.getWebAdminPath());
            if (results.getCode() == 0) {//有登陆信息，但无角色权限
                if (IsApi) {
                    inv.getController().renderJson(Results.n(93, "无权操作").setData(Jmode.n().set("act_id", act_ids)));
                } else {
                    inv.getController().setAttr("act_ids", act.getAct_id());
                    inv.getController().setAttr("needrole", pass_roles);
                    inv.getController().render("/WEB-INF/resource/pages/error/norole.html");
                }
            } else {//登陆信息异常
                if (results.getCode() == 93) {//没有登陆信息
                    if (IsApi) {
                        inv.getController().renderJson(JsonResult.n(94, ""));
                    } else {
                        inv.getController().render("/WEB-INF/resource/pages/error/nologin.html");
                    }
                } else if (results.getCode() == 91) {//登陆已过期
                    if (IsApi) {
                        inv.getController().renderJson(JsonResult.n(91, ""));
                    } else {
                        inv.getController().render("/WEB-INF/resource/pages/error/nologin.html");
                    }
                } else {//其它异常
                    if (IsApi) {
                        inv.getController().renderJson(JsonResult.n(99, results.getMsg()));
                    } else {
                        inv.getController().renderText(results.getMsg());
                    }
                }
            }
        }
    }

    /**
     * 取得用户id
     *
     * @return
     */
    protected int getEmpID(HttpServletRequest request) {
        String jwt = WebSite.getJwt(request);
        Results results = JwtUtil.validateJWT(jwt);
        if (results.getCode() == 0) {
            JwtUtil.JwtSubject js = results.getObject(JwtUtil.JwtSubject.class);
            return js.getUserid();
        }
        return 0;
    }


    /**
     * 取得sesssonid
     *
     * @return
     */
    protected String getSessId(HttpServletRequest request) {
        String jwt = WebSite.getJwt(request);
        Results results = JwtUtil.validateJWT(jwt);
        if (results.getCode() == 0) {
            JwtUtil.JwtSubject js = results.getObject(JwtUtil.JwtSubject.class);
            return js.getId();
        }
        return "underfind";
    }


    /**
     * 取得验证表数据
     * 1从postdata取
     * 2从json中最
     * 兼容两种传入数据方式
     *
     * @param controller
     */
    private Datas getData(Controller controller) {
        Datas d = null;
        String req = controller.getRawData();
        if (req != null && req.length() > 0) d = JsonUtil.json2Datas(req);
        if (d == null || d.isEmpty()) {
            d = JsonUtil.json2Datas(controller.getPara("postdata"));
        }
        return d;
    }

    /**
     * 把request数据转换成JSON
     *
     * @param controller
     * @return
     */
    private String getRequestJson(Controller controller) {
        Datas d = getData(controller);
        if (d == null) return "";
        return d.toJson();
    }
}
